package com.kindsoft.demo.services.impl;

import com.kindsoft.demo.ldap.Person;
import com.kindsoft.demo.ldap.PersonMapper;
import com.kindsoft.demo.ldap.User;
import com.kindsoft.demo.services.LdapService;
import java.util.List;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.*;

//import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ldap.core.*;
import org.springframework.ldap.filter.Filter;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.security.ldap.LdapUtils;
import org.springframework.stereotype.Service;

import static org.springframework.ldap.query.LdapQueryBuilder.query;

@Service
public class LdapServiceImpl implements LdapService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private LdapTemplate ldapTemplate;

    @Value("${ldap.domainName}")
    private String ldapDomainName;

    @Value("${ldap.base}")
    private String ldapBaseDn;

    /**
     * 获取部门列表
     */
    @Override
    public List<String> getDepartmentList(String ldapBase, Filter filter) {
        return ldapTemplate.search(ldapBase, filter.encode(), new AttributesMapper() {
            @Override
            public String mapFromAttributes(Attributes attr) throws NamingException {
                log.info("<getDepartmentList> attr: " + attr);
                String name = (String)attr.get("cn").get();
                return name;
            }
        });
    }

    /**
     * 获取用户列表
     */
    @Override
    public List<User> getPersonList(String ldapBase, Filter filter) {
        return ldapTemplate.search(ldapBase, filter.encode(), new AttributesMapper() {
            @Override
            public User mapFromAttributes(Attributes attr) throws NamingException {
                User person = new User();
                String distingugihedName = (String)attr.get("distinguishedName").get();
                person.setUserName((String)attr.get("username").get());
                person.setEmail((String)attr.get("mail").get());
//                person.setRealName((String)attr.get("name").get());
//                if (null != attr.get("mobile")) {
//                    person.setMobile((String) attr.get("mobile").get());
//                }
//                if (null != attr.get("telephoneNumber")) {
//                    person.setPhone((String) attr.get("telephoneNumber").get());
//                }
//                person.setLdapFlag(1);
//                String departmentName = StringUtils.substringAfter(distingugihedName.split(",")[1], "OU=");
//                person.setUnitName(departmentName);
                return person;
            }
        });
    }

    /*
     * 身份认证
     */
    @Override
    public boolean authenticate(String userName, String password) {
        log.info("<authenticate> userName: " + userName);


        //String userDomainName = getDnForUser(userName);
        String userDomainName = userName + ldapDomainName;
        if (ldapDomainName.contains("%s")) {
            userDomainName = String.format(ldapDomainName, userName);
        }
        log.info("<authenticate> userDomainName: " + userDomainName);

        DirContext ctx = null;

        try {
            ctx = ldapTemplate.getContextSource().getContext(userDomainName,password);
            log.info("<authenticate> auth success!");
            return true;
        } catch(Exception e) {
            log.error("<authenticate> error: " + e.getMessage(), e);
            e.printStackTrace();
        } finally {
            LdapUtils.closeContext(ctx);
        }

        return false;
    }

    @Override
    public List<Person> search(String objectClass) {
        List<Person> personList = ldapTemplate.search(query().where("objectClass").is(objectClass), new PersonMapper());
        personList.forEach(p -> {
            log.info("<search> p=" + p);
        });
        return personList;
    }

    /**
     * 创建用户（比较推荐）
     * @param name
     */
    @Override
    public void create(String name, String dn) {
        Name userDn = LdapNameBuilder.newInstance(dn).build();
        if(!dn.contains("ou=")) {
            userDn = LdapNameBuilder.newInstance().add("cn", "Users").add("cn", dn).build();
        }
        DirContextAdapter context = new DirContextAdapter(userDn);
//        context.setAttributeValues("objectClass", new String[] {"top", "person", "user"});
        context.setAttributeValues("objectClass", new String[] {"top", "inetOrgPerson", "person"});
        context.setAttributeValue("sn", name);
        context.setAttributeValue("cn", name);
        context.setAttributeValue("description", "description");
        ldapTemplate.bind(context);
    }

    /**
     * 更新用户
     * @param name
     */
    @Override
    public void update(String name) {
        // "uid=bob,ou=People"
        log.info("<update> name: " + name);
        Name userDn = LdapNameBuilder.newInstance(name).build();
        DirContextOperations context = ldapTemplate.lookupContext(userDn);
        context.setAttributeValue("mail", "sky@seecent.com");
        ldapTemplate.modifyAttributes(context);
    }

    /**
     * 删除用户
     * @param name
     */
    @Override
    public void delete(String name) {
        Name userDn = LdapNameBuilder.newInstance("cn=zhangting,ou=234").build();
        ldapTemplate.unbind(userDn);
    }
}
